package service_sys

import (
	"context"
	"go_web/internal/model/model_sys"
	"go_web/internal/repo/repo_sys"
	"go_web/internal/req/req_sys"
	"go_web/internal/res/res_sys"
	"go_web/pkg/req"
	"go_web/pkg/res"
	"go_web/pkg/utils"
	"math"
	"strings"

	"github.com/fatih/structs"
	"github.com/jinzhu/copier"
	"gorm.io/gen"
	"gorm.io/gen/field"
)

type SysOrgService struct{}

// 创建新的 SysOrgService
func NewSysOrgService() *SysOrgService {
	return &SysOrgService{}
}

// 分页查询
func (*SysOrgService) Page(c context.Context, pageReq req_sys.SysOrgPageReq) (*res.PageRes, error) {
	offset := (pageReq.Page - 1) * pageReq.PageSize
	q := repo_sys.SysOrg.WithContext(c)
	if pageReq.ParentId != nil {
		q = q.Where(repo_sys.SysOrg.ParentID.Eq(*pageReq.ParentId))
	}

	if pageReq.SearchKey != nil && strings.Trim(*pageReq.SearchKey, " ") != "" {
		q = q.Where(repo_sys.SysOrg.Name.Like("%" + *pageReq.SearchKey + "%"))
	}
	// 排序处理
	if pageReq.SortField != nil {
		sortField := utils.ConvertToSnakeCase(*pageReq.SortField)
		orderFieldExpr := field.NewUnsafeFieldRaw(sortField)
		if pageReq.SortOrder != nil {
			if *pageReq.SortOrder == "asc" {
				q = q.Order(orderFieldExpr.Asc())
			} else {
				q = q.Order(orderFieldExpr.Desc())
			}
		} else {
			q = q.Order(orderFieldExpr.Asc())
		}
	}

	// 执行分页查询
	list, count, err := q.FindByPage(offset, pageReq.PageSize)
	if err != nil {
		return nil, err
	}

	// 计算总页数
	page := res.PageRes{
		List:     list,
		Total:    count,
		Page:     pageReq.Page,
		PageSize: pageReq.PageSize,
		Pages:    int64(math.Ceil(float64(count) / float64(pageReq.PageSize))),
	}

	return &page, nil
}

// 添加 SysOrg 已开启事务
func (*SysOrgService) Add(c context.Context, addReq req_sys.SysOrgAddReq) (int64, error) {
	var SysOrg model_sys.SysOrg
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysOrg.WithContext(c)
		err := copier.Copy(&SysOrg, &addReq)
		if err != nil {
			return err
		}
		err = q.Create(&SysOrg)
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return SysOrg.ID, nil
}

// 编辑 SysOrg 已开启事务
func (*SysOrgService) Edit(c context.Context, editReq req_sys.SysOrgEditReq) (int64, error) {
	var result gen.ResultInfo
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		q := tx.SysOrg.WithContext(c).Where(repo_sys.SysOrg.ID.Eq(editReq.ID))
		SysOrg, err := q.First()
		if err != nil {
			return err
		}
		err = copier.Copy(&SysOrg, &editReq)
		if err != nil {
			return err
		}
		result, err = q.Updates(structs.Map(SysOrg))
		if err != nil {
			return err
		}
		return nil
	})

	if err != nil {
		if utils.IsOptimisticLockError(err) {
			return -1, nil // 乐观锁报错（版本不一致）
		}
		return 0, err
	}
	return result.RowsAffected, nil
}

// 删除 SysOrg 已开启事务
func (*SysOrgService) Delete(c context.Context, idsReq req.IdsReq) (int64, error) {
	var result gen.ResultInfo
	err := repo_sys.Q.Transaction(func(tx *repo_sys.Query) error {
		ids, err := idsReq.ToInt64Slice()
		if err != nil {
			return err
		}
		// 先删除组织
		_, err = repo_sys.SysOrg.WithContext(c).Where(repo_sys.SysOrg.ID.In(ids...)).Delete()
		if err != nil {
			return err
		}
		// 再删除组织用户关联
		_, err = repo_sys.SysOrgUser.WithContext(c).Where(repo_sys.SysOrgUser.OrgID.In(ids...)).Delete()
		if err != nil {
			return err
		}
		return nil
	})
	if err != nil {
		return 0, err
	}
	return result.RowsAffected, nil
}

// 查看 SysOrg 详情
func (*SysOrgService) Detail(c context.Context, userId int64) (*res_sys.SysOrgDetailRes, error) {
	q := repo_sys.SysOrg.WithContext(c)
	var sysOrgDetailRes *res_sys.SysOrgDetailRes = &res_sys.SysOrgDetailRes{}
	SysOrg, err := q.Where(repo_sys.SysOrg.ID.Eq(userId)).First()
	if err != nil {
		return nil, err
	}
	copier.Copy(sysOrgDetailRes, SysOrg)
	if sysOrgDetailRes.ParentId != 0 {
		parentOrg, err := q.Where(repo_sys.SysOrg.ParentID.Eq(sysOrgDetailRes.ParentId)).First()
		if err != nil {
			return nil, err
		}
		sysOrgDetailRes.ParentName = parentOrg.Name
	}
	if sysOrgDetailRes.DirectorId != 0 {
		director, err := repo_sys.SysUser.WithContext(c).Where(repo_sys.SysUser.ID.Eq(sysOrgDetailRes.DirectorId)).First()
		if err != nil {
			return nil, err
		}
		sysOrgDetailRes.DirectorName = director.Nickname
	}

	return sysOrgDetailRes, nil
}

// 查看组织树列表
func (*SysOrgService) TreeList(c context.Context) ([]*res_sys.SysOrgRes, error) {
	var allOrgs []*model_sys.SysOrg
	allOrgs, err := repo_sys.SysOrg.WithContext(c).FindAllOrgs()
	if err != nil {
		return nil, err
	}
	var allOrgsMapValues []*res_sys.SysOrgRes
	var allOrgsMap map[int64]*res_sys.SysOrgRes = make(map[int64]*res_sys.SysOrgRes)
	for _, org := range allOrgs {
		var orgRes *res_sys.SysOrgRes = &res_sys.SysOrgRes{}
		copier.Copy(orgRes, &org)
		if orgRes.Children == nil {
			orgRes.Children = []*res_sys.SysOrgRes{}
		}
		allOrgsMap[org.ID] = orgRes
		allOrgsMapValues = append(allOrgsMapValues, orgRes)
	}
	var sysOrgResList []*res_sys.SysOrgRes
	for _, orgRes := range allOrgsMapValues {
		if orgRes.ParentId == 0 { // 无父节点
			sysOrgResList = append(sysOrgResList, orgRes)
		} else {
			// 有父节点
			parent := allOrgsMap[orgRes.ParentId]
			if parent != nil {
				parent.Children = append(parent.Children, orgRes)
			}
		}
	}

	return sysOrgResList, nil
}
